﻿using System;
using System.Windows.Forms;
using OSGeo.GDAL;

namespace 直方图均衡化
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog op = new OpenFileDialog())
            {
                op.Filter = "影像|*.tif";
                if (op.ShowDialog() == DialogResult.OK)
                {
                    textBox1.Text = op.FileName;
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(textBox1.Text.Trim()))
                return;
            Gdal.AllRegister();
            Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
            Driver dr = Gdal.GetDriverByName("GTiff");
            Dataset ds = Gdal.Open(textBox1.Text, OSGeo.GDAL.Access.GA_ReadOnly);
            Dataset dst = null;
            for (int iBand = 1; iBand <= ds.RasterCount; iBand++)
            {

                Band band = ds.GetRasterBand(iBand);
                double pdfMin, pdfMax, pdfMean, pdfStdDev;
                band.GetStatistics(0, 1, out pdfMin, out pdfMax, out pdfMean, out pdfStdDev);
                int[] histData = new int[(int)(pdfMax - pdfMin)+1];
                band.GetHistogram(pdfMin-0.5, pdfMax+0.5, (int)(pdfMax - pdfMin+1), histData, 0, 1, null, "");
                if (dst == null)
                {
                    dst = dr.Create("d:/testss.tif", band.XSize, band.YSize, ds.RasterCount, DataType.GDT_Byte, null);
                    double[] adfGeoTransform = new double[6];
                    ds.GetGeoTransform(adfGeoTransform);
                    dst.SetGeoTransform(adfGeoTransform);
                    string pszProjection = ds.GetProjection();
                    if (!string.IsNullOrEmpty(pszProjection))
                        dst.SetProjection(pszProjection);                    
                    string[] metadata = ds.GetMetadata("");
                    if (metadata.Length > 0)
                    {
                        dst.SetMetadata(metadata, "");                    
                    }
                }

                int[] panCumHist = new int[histData.Length];
                int total = 0;
                for (int i = 0; i < histData.Length; i++)
                {
                    panCumHist[i] = total + histData[i] / 2;
                    total += histData[i];
                }

                int[] panLUT = new int[256];
                int iLUT;

                for (iLUT = 0; iLUT < 256; iLUT++)
                {
                    int iHist = (iLUT * histData.Length) / 256;
                    int nValue = (int)((panCumHist[iHist] * 256) / total);
                    panLUT[iLUT] = Math.Max(0, Math.Min(256 - 1, nValue));
                }

                int[] buffers = new int[band.XSize * band.YSize];
                byte[] buffersdst = new byte[band.XSize * band.YSize];
                band.ReadRaster(0, 0, band.XSize, band.YSize, buffers, band.XSize, band.YSize, 0, 0);
                Band banddst = dst.GetRasterBand(iBand);
                banddst.ReadRaster(0, 0, band.XSize, band.YSize, buffersdst, band.XSize, band.YSize, 0, 0);
                int bHaveNoData;
                double fNoData;
                band.GetNoDataValue(out fNoData, out bHaveNoData);
                double dfScale = 256 / (pdfMax - pdfMin);
                for (int i = 0; i < buffers.Length; i++)
                {
                    if (bHaveNoData == 1 && buffers[i] == fNoData)
                    {
                        buffers[i] = (byte)fNoData;
                        continue;
                    }

                    int iBin = (int)((buffers[i] - pdfMin) * dfScale);
                    iBin = Math.Max(0, Math.Min(255, iBin));
                    buffersdst[i] = (byte)panLUT[iBin];
                }
                banddst.WriteRaster(0, 0, band.XSize, band.YSize, buffersdst, band.XSize, band.YSize, 0, 0);                
            }
            ds.Dispose();
            dst.FlushCache();
            dst.Dispose();
            pictureBox1.Load("d:/testss.tif");
        }
    }
}
